home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / os2 / cpostsrc.arj / CPOST.C < prev    next >
Text File  |  1994-02-07  |  32KB  |  891 lines

  1. /*------------------------------------------------------------------
  2.  * cPost.c  : c language formatter
  3.  *------------------------------------------------------------------
  4.  * 10-10-91 originally by Patrick J. Mueller
  5.  * 12-03-92 converted from cBook to cPost
  6.  *------------------------------------------------------------------*/
  7.  
  8. #define PROGRAM_VERS  "1.4"
  9. #define PROGRAM_NAME  "cPost"
  10. #define PROGRAM_YEAR  "1994"
  11. #define PROGRAM_AUTH  "Patrick J. Mueller"
  12. #define PROGRAM_ADDR  "(pmuellr@vnet.ibm.com)"
  13. #define PROGRAM_ENVV  "CPOST"
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdarg.h>
  19. #include <signal.h>
  20. #include <time.h>
  21.  
  22. #include "parsearg.h"
  23.  
  24. #include "ctok.h"
  25. #define DEFINE_GLOBALS
  26. #include "cpost.h"
  27. #include "tokfile.h"
  28.  
  29. #include "cposthdr.h"
  30.  
  31. /*---------------------------------------------------------------
  32.  * global variables
  33.  *---------------------------------------------------------------*/
  34. int  AllDone = 0;
  35.  
  36. static char *ReservedTokens[] =
  37.    {
  38.    /*---------------------------------------------------------------
  39.     * data types
  40.     *---------------------------------------------------------------*/
  41.    "auto", "char", "const", "double", "enum", "extern", "float", "int",
  42.    "long", "register", "short", "signed", "static", "struct", "union",
  43.    "unsigned", "void", "volatile",
  44.  
  45.    /*---------------------------------------------------------------
  46.     * other keywords
  47.     *---------------------------------------------------------------*/
  48.    "break", "case", "continue", "default", "do", "else", "for", "goto",
  49.    "if", "return", "sizeof", "switch", "typedef", "while",
  50.  
  51.    /*---------------------------------------------------------------
  52.     * saa c extensions
  53.     *---------------------------------------------------------------*/
  54.    "_Packed","_System","_Optlink", "_Far16", "_Cdecl", "_Pascal"
  55.    };
  56.  
  57. /*------------------------------------------------------------------
  58.  * c++ reserved words
  59.  *------------------------------------------------------------------*/
  60. static char *CppReservedTokens[] =
  61.    {
  62.    "catch", "class", "delete", "friend", "inline", "new", "operator",
  63.    "private", "protected", "public", "template", "this", "throw", "try",
  64.    "virtual"
  65.    };
  66.  
  67.  
  68. /*------------------------------------------------------------------
  69.  * generate an error message and exit
  70.  *------------------------------------------------------------------*/
  71. void cPostError(
  72.    int   exitCode,
  73.    char *format,
  74.    ...
  75.    )
  76.    {
  77.    va_list vlist;
  78.  
  79.    fprintf(stderr,"%s : ",PROGRAM_NAME);
  80.  
  81.    va_start(vlist,format);
  82.    vfprintf(stderr,format,vlist);
  83.    va_end(vlist);
  84.  
  85.    fprintf(stderr,"\n");
  86.  
  87.    if (exitCode)
  88.       exit(exitCode);
  89.    }
  90.  
  91. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  92. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  93.  
  94. /*------------------------------------------------------------------
  95.  * print some help, assuming me is argv[0]
  96.  *------------------------------------------------------------------*/
  97. static void Usage(void)
  98.    {
  99.    fprintf(stderr,"%s %s by %s %s\n",PROGRAM_NAME,PROGRAM_VERS,PROGRAM_AUTH,PROGRAM_ADDR);
  100.    fprintf(stderr,"\n");
  101.    fprintf(stderr,"usage:\n");
  102.    fprintf(stderr,"   %s <options> <filespec> <filespec> ...\n",PROGRAM_NAME);
  103.    fprintf(stderr,"is used to produce a listing of C language files in PostScript\n");
  104.    fprintf(stderr,"format.  The PostScript output is written to stdout.\n\n");
  105.    fprintf(stderr,"where:\n");
  106.    fprintf(stderr,"   <filespec> is a filespec matching C language files.\n\n");
  107.    fprintf(stderr,"Valid options are:\n");
  108.    fprintf(stderr,"   -b[+|-]             - enable/disable bracketing around braces\n");
  109.    fprintf(stderr,"   -cext1,ext2,...     - treat files with extention ext1 and ext2 as C files\n");
  110.    fprintf(stderr,"   -d[+|-]             - enable/disable duplex\n");
  111.    fprintf(stderr,"   -hext1,ext2,...     - treat files with extention ext1 and ext2 as H files\n");
  112.    fprintf(stderr,"   -ifile1;file2;...   - imbed files into output\n");
  113.    fprintf(stderr,"   -kk1,k2,...         - treat k1, k2 as reserved (key=c++ adds c++ keywords)\n");
  114.    fprintf(stderr,"   -n#                 - separate line numbers from lines with # spaces\n");
  115.    fprintf(stderr,"   -n0                 - do not generate line numbers\n");
  116.    fprintf(stderr,"   -ofile              - output written to file (instead of stdout)\n");
  117.    fprintf(stderr,"   -p[+|-]             - enable/disable page break at functions\n");
  118.    fprintf(stderr,"   -rfile1;file2,...   - replace default PS procs with contents of files\n");
  119.    fprintf(stderr,"   -snt or -stn        - sort files by name/type or type/name\n");
  120.    fprintf(stderr,"   -t#                 - expand tabs to # columns\n");
  121.    fprintf(stderr,"   -wf1,f2;f3,f4       - prepend files f1, f2 to output, append files f3, f4\n");
  122.    fprintf(stderr,"   -xx,y               - coordinates for page adjustment\n");
  123.    fprintf(stderr,"   -ypath              - path to use for temporary files\n");
  124.    fprintf(stderr,"   -?                  - display this help\n\n");
  125.    fprintf(stderr,"Default options are:\n");
  126.    fprintf(stderr,"   -b+ -d- -cc -hh -n2 -p+ -stn -t4 -x0,0\n");
  127.    fprintf(stderr,"Options may also be set in the environment variable %s.\n",PROGRAM_ENVV);
  128.  
  129.    exit(1);
  130.    }
  131.  
  132. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  133. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  134.  
  135. /*------------------------------------------------------------------
  136.  * add default key words to reserved hash
  137.  *------------------------------------------------------------------*/
  138. void InitializeReservedHash(
  139.    Info *info,
  140.    char *keyList
  141.    )
  142.    {
  143.    int   i;
  144.    char *part;
  145.  
  146.    /*---------------------------------------------------------------
  147.     * create hash table
  148.     *---------------------------------------------------------------*/
  149.    info->reservedHash = HashCreate(sizeof(char *),
  150.                                   30,
  151.                                   (HashFunc *)IdentHash,
  152.                                   (ListCompareFunc *)IdentCompare,
  153.                                   cPostNoMem);
  154.  
  155.    if (!info->reservedHash)
  156.       cPostError(1,"error creating reserved word hash table");
  157.  
  158.    for (i=0; i<sizeof(ReservedTokens)/sizeof(char *); i++)
  159.       if (!HashAdd(info->reservedHash,&(ReservedTokens[i])))
  160.          cPostError(1,"error adding reserved word '%s' to hash table",
  161.                     ReservedTokens[i]);
  162.  
  163.    /*---------------------------------------------------------------
  164.     * loop through the comma separated keys ...
  165.     *---------------------------------------------------------------*/
  166.    part = strtok(keyList,",");
  167.    while (part)
  168.       {
  169.       /*------------------------------------------------------------
  170.        * special c++ token
  171.        *------------------------------------------------------------*/
  172.       if (!Stricmp("c++",part))
  173.          {
  174.          for (i=0; i<sizeof(CppReservedTokens)/sizeof(char *); i++)
  175.             if (!HashAdd(info->reservedHash,&(CppReservedTokens[i])))
  176.                cPostError(1,"error adding reserved word '%s' to hash table",
  177.                           CppReservedTokens[i]);
  178.  
  179.          }
  180.  
  181.       /*------------------------------------------------------------
  182.        * file name
  183.        *------------------------------------------------------------*/
  184.       else if (('@' == part[0]) && (1 != strlen(part)))
  185.          {
  186.          TokFileInfo  tfi;
  187.          char        *key;
  188.  
  189.          part++;
  190.  
  191.          tfi = TokFileOpen(part);
  192.  
  193.          if (!tfi)
  194.             cPostError(0,"error opening file '%s' for reading",part);
  195.  
  196.          else
  197.             {
  198.             while (NULL != (part = TokFileNext(tfi)))
  199.                {
  200.                key = malloc(1 + strlen(part));
  201.                if (!key)
  202.                   cPostError(1,"out of memory!!");
  203.  
  204.                strcpy(key,part);
  205.  
  206.                if (!HashAdd(info->reservedHash,&key))
  207.                   cPostError(0,"error adding reserved word '%s' to hash table; word ignored",
  208.                                 key);
  209.                }
  210.             }
  211.          }
  212.  
  213.       /*------------------------------------------------------------
  214.        * plain old token
  215.        *------------------------------------------------------------*/
  216.       else if (!HashAdd(info->reservedHash,&part))
  217.          {
  218.          cPostError(0,"error adding reserved word '%s' to hash table; word ignored",part);
  219.          }
  220.  
  221.       part = strtok(NULL,",");
  222.       }
  223.    }
  224.  
  225. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  226. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  227.  
  228. /*------------------------------------------------------------------
  229.  * clean up file list
  230.  *------------------------------------------------------------------*/
  231. static int CleanUpFileList(
  232.    File     *file,
  233.    Info     *info
  234.    )
  235.    {
  236.    PageEject *pe;
  237.  
  238.    if (!(info->oDebug & 1) && (file->tempName))
  239.       remove(file->tempName);
  240.  
  241.    /*---------------------------------------------------------------
  242.     * free up file fields
  243.     *---------------------------------------------------------------*/
  244.    free(file->name);
  245.    free(file->pathName);
  246.  
  247.    if (*(file->ext))
  248.       free(file->ext);
  249.  
  250.    if (file->tempName)
  251.       free(file->tempName);
  252.  
  253.    /*---------------------------------------------------------------
  254.     * free function lists
  255.     *---------------------------------------------------------------*/
  256.    ListDestroy(file->funcDefList);
  257.    ListDestroy(file->funcProList);
  258.  
  259.    /*---------------------------------------------------------------
  260.     * free page eject list
  261.     *---------------------------------------------------------------*/
  262.    pe = file->breakList;
  263.    while (pe)
  264.       {
  265.       PageEject *next;
  266.  
  267.       next = pe->next;
  268.       free(pe);
  269.       pe   = next;
  270.       }
  271.  
  272.    return 0;
  273.    }
  274.  
  275. /*------------------------------------------------------------------
  276.  * clean up function list
  277.  *------------------------------------------------------------------*/
  278. static int CleanUpFuncList(
  279.    Function *func,
  280.    Info     *info
  281.    )
  282.    {
  283.    ListDestroy(func->callsList);
  284.    ListDestroy(func->calledByList);
  285.  
  286.    free(func->name);
  287.  
  288.    return 0;
  289.    }
  290.  
  291. /*------------------------------------------------------------------
  292.  * atexit processing
  293.  *------------------------------------------------------------------*/
  294. static void RunAtExit(void)
  295.    {
  296.  
  297.    if (!AllDone)
  298.       fprintf(stderr,"%s : Program terminated.\n",PROGRAM_NAME);
  299.  
  300.    /*---------------------------------------------------------------
  301.     * erase any temporary files we might have open
  302.     *---------------------------------------------------------------*/
  303.    if (!AllDone)
  304.       fprintf(stderr,"%s : Cleaning up temporary files.\n",PROGRAM_NAME);
  305.  
  306.    ListIterate(info.fileList,(ListIterateFunc *)CleanUpFileList,&info);
  307.  
  308.    /*---------------------------------------------------------------
  309.     * destroy file list
  310.     *---------------------------------------------------------------*/
  311.    ListDestroy(info.fileList);
  312.  
  313.    /*---------------------------------------------------------------
  314.     * destroy hash tables
  315.     *---------------------------------------------------------------*/
  316.    HashDestroy(info.identHash);
  317.    HashDestroy(info.reservedHash);
  318.  
  319.    /*---------------------------------------------------------------
  320.     * destroy function list
  321.     *---------------------------------------------------------------*/
  322.    ListIterate(info.funcTree,(ListIterateFunc *)CleanUpFuncList,&info);
  323.    ListDestroy(info.funcTree);
  324.  
  325.    /*---------------------------------------------------------------
  326.     * dump memory (if debug enabled
  327.     *---------------------------------------------------------------*/
  328. #if defined(__DEBUG_ALLOC__)
  329.    _dump_allocated(0);
  330. #endif
  331.    }
  332.  
  333. /*------------------------------------------------------------------
  334.  * signal handler for program interruption
  335.  *------------------------------------------------------------------*/
  336. void SignalHandler(int sig)
  337.    {
  338.    exit(1);
  339.    }
  340.  
  341. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  342. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  343.  
  344. /*------------------------------------------------------------------
  345.  * print function name symbol defintions
  346.  *------------------------------------------------------------------*/
  347. static int PrintFunctionDefinition(
  348.    Function *func,
  349.    Info     *info
  350.    )
  351.    {
  352.    fprintf(info->oFile,
  353.            ".nameit symbol=fn%4.4d gmltype=hp%c size='+%d' text='%s'\n",
  354.            func->id, '2', 3, func->name);
  355.  
  356.    return 0;
  357.    }
  358.  
  359. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  360. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  361.  
  362. /*------------------------------------------------------------------
  363.  * compute calls and called bys, replace if > than max
  364.  *------------------------------------------------------------------*/
  365. static int CountFunctionRefs(
  366.    Function *func,
  367.    Info     *info
  368.    )
  369.    {
  370.    int count;
  371.  
  372.    count  = ListCount(func->callsList);
  373.    count += ListCount(func->calledByList);
  374.  
  375.    if (count > info->count1)
  376.       info->count1 = count;
  377.  
  378.    return 0;
  379.    }
  380.  
  381. /*------------------------------------------------------------------
  382.  * get maximum number of calls and called bys for all the functions
  383.  * so figure out which table to use
  384.  *------------------------------------------------------------------*/
  385. int GetMaxFuncTableEntries(
  386.    Info      *info
  387.    )
  388.    {
  389.  
  390.    info->count1 = 0;
  391.  
  392.    ListIterate(info->funcTree,
  393.                (ListIterateFunc *)CountFunctionRefs,
  394.                info);
  395.  
  396.    return info->count1;
  397.    }
  398.  
  399. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  400. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  401.  
  402. /*------------------------------------------------------------------
  403.  * parse command line for options
  404.  *------------------------------------------------------------------*/
  405. static void GetOptions(
  406.    int   *argc,
  407.    char  *argv[],
  408.    Info  *info
  409.    )
  410.    {
  411.    int            oHelp;
  412.    char          *oBrack;
  413.    char          *oTabs;
  414.    char          *oCtype;
  415.    char          *oHtype;
  416.    char          *oSort;
  417.    char          *oFile;
  418.    char          *oSpace;
  419.    char          *oKeys;
  420.    char          *oBreak;
  421.    char          *oTemp;
  422.    char          *oImbed;
  423.    char          *oDuplex;
  424.    char          *oXlate;
  425.    char          *numLeft;
  426.    char          *s1;
  427.    char          *s2;
  428.    char          *oWrap;
  429.    char          *oRepHdr;
  430.  
  431.    /*---------------------------------------------------------------
  432.     * parse arguments
  433.     *---------------------------------------------------------------*/
  434.    parsearg(argc,argv,0,PROGRAM_ENVV,"-",
  435.             "? b@ c@ d@ h@ k@ i@ n@ o@ p@ r@ s@ t@ w@ x@ y@",
  436.             &oHelp,&oBrack,&oCtype,&oDuplex,&oHtype,&oKeys,&oImbed,
  437.             &oSpace,&oFile,&oBreak,&oRepHdr,&oSort,&oTabs,&oWrap,
  438.             &oXlate,&oTemp);
  439.  
  440.    /*---------------------------------------------------------------
  441.     * check parms
  442.     *---------------------------------------------------------------*/
  443.    if (oHelp || (*argc < 2))
  444.       Usage();
  445.  
  446.    if ('?' == *argv[1])
  447.       Usage();
  448.  
  449.    /*---------------------------------------------------------------
  450.     * apply option defaults
  451.     *---------------------------------------------------------------*/
  452.    if ((NULL == oBrack ) || ('\0' == *oBrack ))  oBrack  = "+";
  453.    if ((NULL == oCtype ) || ('\0' == *oCtype ))  oCtype  = "c";
  454.    if ((NULL == oDuplex) || ('\0' == *oDuplex))  oDuplex = "-";
  455.    if ((NULL == oHtype ) || ('\0' == *oHtype ))  oHtype  = "h";
  456.    if ((NULL == oKeys  ) || ('\0' == *oKeys  ))  oKeys   = "";
  457.    if ((NULL == oImbed ) || ('\0' == *oImbed ))  oImbed  = "";
  458.    if ((NULL == oSpace ) || ('\0' == *oSpace ))  oSpace  = "2";
  459.    if ((NULL == oFile  ) || ('\0' == *oFile  ))  oFile   = NULL;
  460.    if ((NULL == oBreak ) || ('\0' == *oBreak ))  oBreak  = "+";
  461.    if ((NULL == oRepHdr) || ('\0' == *oRepHdr))  oRepHdr = "";
  462.    if ((NULL == oSort  ) || ('\0' == *oSort  ))  oSort   = "tn";
  463.    if ((NULL == oTabs  ) || ('\0' == *oTabs  ))  oTabs   = "4";
  464.    if ((NULL == oWrap  ) || ('\0' == *oWrap  ))  oWrap   = "";
  465.    if ((NULL == oXlate ) || ('\0' == *oXlate ))  oXlate  = "0,0";
  466.    if ((NULL == oTemp  ) || ('\0' == *oTemp  ))  oTemp   = "";
  467.  
  468.    /*---------------------------------------------------------------
  469.     * bracketing option
  470.     *---------------------------------------------------------------*/
  471.    info->oBrack = (int) strtol(oBrack,NULL,10);
  472.    if (0 == info->oBrack)
  473.       {
  474.       if ((1 != strlen(oBrack)) || (NULL == strchr("-+",*oBrack)))
  475.          cPostError(1,"invalid value on -b option");
  476.  
  477.       if ('+' == *oBrack)
  478.          info->oBrack = 1000;
  479.       else
  480.          info->oBrack = 0;
  481.       }
  482.  
  483.    /*---------------------------------------------------------------
  484.     * extensions for C files
  485.     *---------------------------------------------------------------*/
  486.    info->oCtype = oCtype;
  487.  
  488.    /*---------------------------------------------------------------
  489.     * duplex
  490.     *---------------------------------------------------------------*/
  491.    if ((1 != strlen(oDuplex)) || (NULL == strchr("-+",*oDuplex)))
  492.       cPostError(1,"invalid value on -d option");
  493.  
  494.    info->oDuplex  = ('+' == *oDuplex);
  495.  
  496.    /*---------------------------------------------------------------
  497.     * extensions for H files
  498.     *---------------------------------------------------------------*/
  499.    info->oHtype = oHtype;
  500.  
  501.    /*---------------------------------------------------------------
  502.     * reserved words
  503.     *---------------------------------------------------------------*/
  504.    InitializeReservedHash(info,oKeys);
  505.  
  506.    /*---------------------------------------------------------------
  507.     * imbed option
  508.     *---------------------------------------------------------------*/
  509.    info->oImbed  = oImbed;
  510.  
  511.    /*---------------------------------------------------------------
  512.     * space option
  513.     *---------------------------------------------------------------*/
  514.    info->oSpace = (int) strtol(oSpace,&numLeft,10);
  515.    if (*numLeft || (info->oSpace < 0))
  516.       cPostError(1,"invalid value on -n option");
  517.  
  518.    /*---------------------------------------------------------------
  519.     * output file option
  520.     *---------------------------------------------------------------*/
  521.    if (NULL == oFile)
  522.       info->oFile = stdout;
  523.    else
  524.       {
  525.       info->oFile = fopen(oFile,"w");
  526.       if (NULL == info->oFile)
  527.          cPostError(1,"error opening output file %s for writing",oFile);
  528.       }
  529.  
  530.    /*---------------------------------------------------------------
  531.     * page break option
  532.     *---------------------------------------------------------------*/
  533.    if ((1 != strlen(oBreak)) || (NULL == strchr("-+",*oBreak)))
  534.       cPostError(1,"invalid value on -p option");
  535.  
  536.    info->oBreak  = ('+' == *oBreak);
  537.  
  538.    /*---------------------------------------------------------------
  539.     * replace PS header
  540.     *---------------------------------------------------------------*/
  541.    info->oRepHdr = oRepHdr;
  542.  
  543.    /*---------------------------------------------------------------
  544.     * sort option
  545.     *---------------------------------------------------------------*/
  546.    if ((0 != Stricmp("nt",oSort)) && (0 != Stricmp("tn",oSort)))
  547.       cPostError(1,"invalid value on -s option");
  548.  
  549.    info->oSort  = Strupr(oSort);
  550.  
  551.    /*---------------------------------------------------------------
  552.     * tabs option
  553.     *---------------------------------------------------------------*/
  554.    info->oTabs = (int) strtol(oTabs,NULL,10);
  555.    if (0 == info->oTabs)
  556.       cPostError(1,"invalid value on -t option");
  557.  
  558.    /*---------------------------------------------------------------
  559.     * wrap PS around output
  560.     *---------------------------------------------------------------*/
  561.    info->oWrapB = strtok(oWrap,";");
  562.    info->oWrapA = strtok(NULL,"");
  563.  
  564.    /*---------------------------------------------------------------
  565.     * translate option
  566.     *---------------------------------------------------------------*/
  567.    s1 = strtok(oXlate,",");
  568.    s2 = strtok(NULL,"");
  569.  
  570.    if (!s1 || !s2)
  571.       cPostError(1,"invalid value on -x option");
  572.  
  573.    info->oXlateX = (int) strtol(s1,NULL,10);
  574.    info->oXlateY = (int) strtol(s2,NULL,10);
  575.  
  576.    /*---------------------------------------------------------------
  577.     * temp path
  578.     *---------------------------------------------------------------*/
  579.    if (!strlen(oTemp))
  580.       info->oTemp = "";
  581.  
  582.    else
  583.       {
  584.       char c;
  585.  
  586.       c = oTemp[strlen(oTemp) - 1];
  587.       if (('\\' == c) || ('/' == c))
  588.          info->oTemp = oTemp;
  589.       else
  590.          {
  591.          info->oTemp = malloc(2+strlen(oTemp));
  592.          strcpy(info->oTemp,oTemp);
  593.          strcat(info->oTemp,"/");
  594.          }
  595.       }
  596.  
  597.  
  598.    }
  599.  
  600. /*------------------------------------------------------------------
  601.  * copy one file stream to another
  602.  *------------------------------------------------------------------*/
  603. void copyFile(
  604.    FILE *fileFrom,
  605.    FILE *fileTo
  606.    )
  607.    {
  608. #define BUFFER_SIZE 8192
  609.    char *buffer;
  610.  
  611.    /*---------------------------------------------------------------
  612.     * allocate buffer
  613.     *---------------------------------------------------------------*/
  614.    buffer = malloc(BUFFER_SIZE);
  615.    if (!buffer)
  616.       cPostError(1,"out of memory!!");
  617.  
  618.    /*---------------------------------------------------------------
  619.     * copy file buffer at a time
  620.     *---------------------------------------------------------------*/
  621.    while (!feof(fileFrom))
  622.       {
  623.       int count;
  624.       count = fread(buffer,1,BUFFER_SIZE,fileFrom);
  625.       fwrite(buffer,1,count,fileTo);
  626.       }
  627.  
  628.    /*---------------------------------------------------------------
  629.     * free the buffer
  630.     *---------------------------------------------------------------*/
  631.    free(buffer);
  632.    }
  633.  
  634. /*------------------------------------------------------------------
  635.  * process the imbed file option
  636.  *------------------------------------------------------------------*/
  637. void processImbedFile(
  638.    char *imbedFileName
  639.    )
  640.    {
  641.    FILE *file;
  642.  
  643.    /*---------------------------------------------------------------
  644.     * while we have imbedFileNames
  645.     *---------------------------------------------------------------*/
  646.    imbedFileName = strtok(imbedFileName,";,");
  647.    while (imbedFileName)
  648.       {
  649.       /*------------------------------------------------------------
  650.        * open the imbed file
  651.        *------------------------------------------------------------*/
  652.       file = fopen(imbedFileName,"r");
  653.  
  654.       /*------------------------------------------------------------
  655.        * print error if not found, or copy it in if found
  656.        *------------------------------------------------------------*/
  657.       if (!file)
  658.          cPostError(0,"unable to open file '%s' for reading",imbedFileName);
  659.       else
  660.          {
  661.          copyFile(file,info.oFile);
  662.          fclose(file);
  663.          }
  664.  
  665.       /*------------------------------------------------------------
  666.        * get next imbed file name
  667.        *------------------------------------------------------------*/
  668.       imbedFileName = strtok(NULL,";,");
  669.       }
  670.    }
  671.  
  672. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  673. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  674.  
  675. /*------------------------------------------------------------------
  676.  * main program
  677.  *------------------------------------------------------------------*/
  678. int main(
  679.    int   argc,
  680.    char *argv[]
  681.    )
  682.    {
  683.    int        i;
  684.    char       dateStr[30];
  685.    struct tm *tm;
  686.    time_t     t;
  687.    char      *origParms;
  688.  
  689.    /*---------------------------------------------------------------
  690.     * check for help
  691.     *---------------------------------------------------------------*/
  692.    if ((1 == argc) || ('?' == *(argv[1])))
  693.       Usage();
  694.  
  695.    /*---------------------------------------------------------------
  696.     * get original parms
  697.     *---------------------------------------------------------------*/
  698.    origParms  = malloc(1);
  699.    *origParms = 0;
  700.  
  701.    for (i=0; i<argc; i++)
  702.       {
  703.       origParms = realloc(origParms,2 + strlen(origParms) + strlen(argv[i]));
  704.       strcat(origParms," ");
  705.       strcat(origParms,argv[i]);
  706.       }
  707.  
  708.    /*---------------------------------------------------------------
  709.     * zero out info
  710.     *---------------------------------------------------------------*/
  711.    memset(&info,0,sizeof(info));
  712.  
  713.    /*---------------------------------------------------------------
  714.     * get options
  715.     *---------------------------------------------------------------*/
  716.    GetOptions(&argc,argv,&info);
  717.  
  718.    /*---------------------------------------------------------------
  719.     * buffer output
  720.     *---------------------------------------------------------------*/
  721. /* setvbuf(info.oFile,NULL,_IOFBF,32000); */
  722.  
  723.    /*---------------------------------------------------------------
  724.     * put filenames in a list
  725.     *---------------------------------------------------------------*/
  726.    info.fileList = ListCreate(sizeof(File),
  727.                               (ListCompareFunc *)FileNameCompare,
  728.                               cPostNoMem);
  729.    if (!info.fileList)
  730.       cPostError(1,"error creating list of files");
  731.  
  732.    for (i=1; i<argc; i++)
  733.       FileSpecAdd(&info,info.fileList,argv[i]);
  734.  
  735.    /*---------------------------------------------------------------
  736.     * check for no files to process
  737.     *---------------------------------------------------------------*/
  738.    if (!ListCount(info.fileList))
  739.       cPostError(1,"no files to process");
  740.  
  741.    /*---------------------------------------------------------------
  742.     * intialize rest of info structure
  743.     *---------------------------------------------------------------*/
  744.    info.funcTree  = ListCreate(sizeof(Function),
  745.                                (ListCompareFunc *)FunctionNameCompare,
  746.                                cPostNoMem);
  747.    if (!info.fileList)
  748.       cPostError(1,"error creating list of functions");
  749.  
  750.    info.identHash   = HashCreate(sizeof(char *),
  751.                                  1000,
  752.                                  (HashFunc *)IdentHash,
  753.                                  (ListCompareFunc *)IdentCompare,
  754.                                  cPostNoMem);
  755.  
  756.  
  757.    if (!info.identHash)
  758.       cPostError(1,"error creating global hash table");
  759.  
  760.    /*---------------------------------------------------------------
  761.     * setup error termination processing
  762.     *---------------------------------------------------------------*/
  763.    atexit(RunAtExit);
  764.    signal(SIGINT,  SignalHandler);
  765.    signal(SIGTERM, SignalHandler);
  766.  
  767. #if defined(OPSYS_OS2) || defined(OPSYS_OS2V2)
  768.    signal(SIGBREAK,SignalHandler);
  769. #endif
  770.  
  771.    /*---------------------------------------------------------------
  772.     * print header
  773.     *---------------------------------------------------------------*/
  774.    fprintf(info.oFile,"%%! PostScript file generated by %s %s\n\n",
  775.            PROGRAM_NAME,PROGRAM_VERS);
  776.  
  777. /*------------------------------------------------------------------
  778.  * a macro to write a line to the output file
  779.  *------------------------------------------------------------------*/
  780. #define p(x) fprintf(info.oFile,"%s\n",x);
  781.  
  782.  
  783.    /*---------------------------------------------------------------
  784.     * write command line and environment variable setting
  785.     *---------------------------------------------------------------*/
  786. #if defined(ECHO_COMMAND_LINE)
  787.       {
  788.       p("%%-----------------------------------------------------------------")
  789.  
  790.       fprintf(info.oFile,"%%%% this file created with the command:\n");
  791.       fprintf(info.oFile,"%%%%   %s\n",origParms);
  792.       fprintf(info.oFile,"%%%% the CPOST environment variable ");
  793.       if (!getenv(PROGRAM_ENVV))
  794.          fprintf(info.oFile,"is not set.\n");
  795.       else
  796.          {
  797.          fprintf(info.oFile,"is set to:\n");
  798.          fprintf(info.oFile,"%%%%   %s\n",getenv(PROGRAM_ENVV));
  799.          }
  800.  
  801.       p("%%-----------------------------------------------------------------")
  802.       p("");
  803.       }
  804. #endif
  805.  
  806.    /*---------------------------------------------------------------
  807.     * write wrapper prefix
  808.     *---------------------------------------------------------------*/
  809.    if (info.oWrapB && strlen(info.oWrapB))
  810.       processImbedFile(info.oWrapB);
  811.  
  812.    /*---------------------------------------------------------------
  813.     * get the time
  814.     *---------------------------------------------------------------*/
  815.    t  = time(NULL);
  816.    tm = localtime(&t);
  817.    strftime(dateStr,sizeof(dateStr)-1,"%m/%d/%y   %H:%M:%S",tm);
  818.  
  819.    p("%%-----------------------------------------------------------------")
  820.    p("%% runtime options and values")
  821.    p("%%-----------------------------------------------------------------")
  822.    p("")
  823.    fprintf(info.oFile,"/printDate (%s) def\n",dateStr);
  824.    fprintf(info.oFile,"/oSpace %d def\n",info.oSpace);
  825.    fprintf(info.oFile,"/oXlate { %d %d translate } def\n",info.oXlateX,info.oXlateY);
  826.    fprintf(info.oFile,"/oDuplex 1 %d eq def\n",info.oDuplex);
  827.    fprintf(info.oFile,"/oNumber 0 %d ne def\n",info.oSpace);
  828.    p("")
  829.  
  830.    /*---------------------------------------------------------------
  831.     * write replaced header ...
  832.     *---------------------------------------------------------------*/
  833.    if (info.oRepHdr && strlen(info.oRepHdr))
  834.       {
  835.       processImbedFile(info.oImbed);
  836.       p("");
  837.       processImbedFile(info.oRepHdr);
  838.       p("");
  839.       }
  840.  
  841.    /*---------------------------------------------------------------
  842.     * or default stuff
  843.     *---------------------------------------------------------------*/
  844.    else
  845.       {
  846.       for (i=0; i< sizeof(Header_1)/sizeof(char *); i++)
  847.          p(Header_1[i]);
  848.  
  849.       p("");
  850.       processImbedFile(info.oImbed);
  851.       p("");
  852.  
  853.       for (i=0; i< sizeof(Header_2)/sizeof(char *); i++)
  854.          p(Header_2[i]);
  855.  
  856.       p("");
  857.       }
  858.  
  859.    /*---------------------------------------------------------------
  860.     * read the files. make copies
  861.     *---------------------------------------------------------------*/
  862.    fprintf(stderr,"Pass 1\n");
  863.    ListIterate(info.fileList,(ListIterateFunc *)Pass1,&info);
  864.  
  865.    /*---------------------------------------------------------------
  866.     * read the copies. write the output file
  867.     *---------------------------------------------------------------*/
  868.    fprintf(stderr,"Pass 2\n");
  869.    ListIterate(info.fileList,(ListIterateFunc *)Pass2,&info);
  870.  
  871.    /*---------------------------------------------------------------*
  872.     * print trailing line feed
  873.     *---------------------------------------------------------------*/
  874.    fprintf(info.oFile,"\n");
  875.  
  876.    /*---------------------------------------------------------------
  877.     * write wrapper suffix
  878.     *---------------------------------------------------------------*/
  879.    if (info.oWrapA && strlen(info.oWrapA))
  880.       processImbedFile(info.oWrapA);
  881.  
  882.    /*---------------------------------------------------------------
  883.     * close file (another line feed for luck!)
  884.     *---------------------------------------------------------------*/
  885.    fprintf(info.oFile,"\n");
  886.    fclose(info.oFile);
  887.  
  888.    AllDone = 1;
  889.    return 0;
  890.    }
  891.